﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Wydatki.WRK.Lotto.DataSets;
using ProgNetComponentsDx.Forms;
using Wydatki.Tools.Lotto;
using DevExpress.XtraBars;
using ProgNetComponentsDx.Browsers;
using System.IO;
using ProgNetComponents.Classes;

namespace Wydatki.WRK.Lotto
{
    public partial class FormLottoWyborKombinacji : MyBaseSqlCeGridForm
    {
        private FormBackgroundWorkMultiThread multiThreadForm;

        object lockDs = new object();
        object lockProgress = new object();
        object lockWynik = new object();
        object lockGlobalFile = new object();

        LottoWyborKombinacjiDataSet copyDs = new LottoWyborKombinacjiDataSet();
        private string fileName ="";

        int max;
        int wynik;
        bool isNew = false;
        DataRow[] rows;
        Browser browser;
        private bool SaveToFile;

        protected override void FinishEdit()
        {
            base.FinishEdit();
            if (isNew)
            {
                teGrupa.EditValue = teGrupa.EditValue.AsString().Trim();
                lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0]["WRK_LWKG_NAZWA"] = teGrupa.EditValue.AsString();
                lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0]["WRK_LWKG_ILOSC_LOSOWAN"] = teIloscLosowan.EditValue.IsNull() ? DBNull.Value : teIloscLosowan.EditValue;
                lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0]["WRK_LWKG_ILOSC_KOMBINACJI"] = teIloscKombinacji.EditValue.IsNull() ? DBNull.Value : teIloscKombinacji.EditValue;
            }
        }

        protected override bool ValidateAll()
        {
            bool result = base.ValidateAll();
            if (result && isNew)
            {
                if (teGrupa.EditValue.IsNull())
                {
                    ValidationMessage = "Podaj nazwę grupy";
                    return false;
                }
                if (browser.IsValidDisplayMember(true, teGrupa.EditValue))
                {
                    ValidationMessage = "Nazwa grupy musi być unikalna";
                    return false;
                }
            }
            return result; 
        }

        protected override void OnLoad()
        {
            base.OnLoad();
            if (!this.IsDesignMode())
            {
                browser = BrowserCache.GetBrowser(Init.InitFormBrowserNames.Glowna.WrkWyborKombinacjiGrupy);
                if (isNew)
                    modeProvider1.CurrentMode = ProgNetComponentsDx.Enums.FormMode.New;
            }
        }
        private bool ValidateActions()
        {
            bool result = true;
            DataRow[] rows = this.lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI.Select("WRK_LWK_POMIN = 0", "WRK_LWK_POZYCJA");
            string type;
            ActionLottoBase action;
            foreach (DataRow r in rows)
            {
                if (!r.CanRead())
                    continue;
                r.ClearErrors();
                type = r["WRK_LWK_TYP"].AsString();
                action = ActionLottoBase.GetActionForWyborKombinacji(type);
                if (action == null)
                {
                    r.SetColumnError("WRK_LWK_TYP", "Zły typ");
                    result = false;
                }
                else
                {
                    if (!action.ValidateParams(r))
                        result = false;
                }
            }
            return result;
        }
        public FormLottoWyborKombinacji()
        {
            InitializeComponent();
        }

        public FormLottoWyborKombinacji(int grupa)
        {
            InitializeComponent();
            
            //bar1.SetItemPosition(bsiLayout, bar1.LinksPersistInfo.Count);
            if (!this.IsDesignMode())
            {
                this.Controls.Remove(gcMain);
                gcMain.Dock = DockStyle.Fill;
                splitContainerControl1.Panel1.Controls.Add(gcMain);
                gcMain.BringToFront();
            }
            this.selectDataProvider1.GetSettings(this).Parameters["GRUPA"].Value = grupa;
        }

        private int CurrentGroup
        {
            get
            {
                return lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0]["WRK_LWKG_ID"].AsInt();
            }
        }
        private void EnsureFile()
        {
            fileName = Application.StartupPath + "\\Kombinacje.txt";
            int i=0;
            while (File.Exists(fileName))
            {
                fileName = Application.StartupPath + "\\Kombinacje " + i++ + ".txt";
            }
        }
        protected override bool GetRecords()
        {
            bool result =  base.GetRecords();
            if (this.selectDataProvider1.GetSettings(this).Parameters["GRUPA"].Value.AsInt() < 0)
            {
                DataRow row = lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY.NewRow();
                lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY.Rows.Add(row);
                modeProvider1.CurrentMode = ProgNetComponentsDx.Enums.FormMode.New;
                Tools.Globals.MdiHelper.RemoveChild(this);
                isNew = true;
            }
            else
            {
                isNew = false;
            }
            this.lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI.WRK_LWK_GRUPAColumn.DefaultValue = lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0].WRK_LWKG_ID;
            teGrupa.EditValue = lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0]["WRK_LWKG_NAZWA"];
            teIloscLosowan.EditValue = lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0]["WRK_LWKG_ILOSC_LOSOWAN"];
            teIloscKombinacji.EditValue = lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0]["WRK_LWKG_ILOSC_KOMBINACJI"];
            changeDetectorProvider1.ResetAll();
            return result;
        }
        
        protected override bool Save()
        {
            bool result = base.Save();
            if (result && isNew)
            {
                isNew = false;
                Tools.Globals.MdiHelper.TryAddChild(this, CurrentGroup);
            }
            return result;
        }
        private void btnWyliczIlosc_Click(object sender, EventArgs e)
        {
            Select(false);
        }
        List<int> WybraneLiczby = new List<int>();
        Dictionary<int, int[]> PrzedzialyLiczb = new Dictionary<int, int[]>();

        private void Select(bool save)
        {
            SaveToFile = save;
            max = Tools.Lotto.LottoLosowaniaTools.LICZBA_KOMBINACJI_6_Z_49;
            wynik = 0;

            FinishEdit();
            if (!ValidateActions())
            {
                this.ShowDxInfoDialog("Błąd walidacji.");
                return;
            }

            copyDs = this.lottoWyborKombinacjiDataSet.Copy() as LottoWyborKombinacjiDataSet;
            rows = copyDs.WRK_LOTTO_WYBOR_KOMBINACJI.Select("WRK_LWK_POMIN = 0", "WRK_LWK_POZYCJA");

            if (rows.Length < 1)
            {
                this.ShowDxInfoDialog("Wybierz wiersze,");
                return;
            }
            WybraneLiczby.Clear();
            if (radioGroup1.EditValue.AsBool())
            {
                for (int i=1; i < 50; i++)
                    WybraneLiczby.Add(i);
            }
            else
            {
                string[] str = teWybraneLiczby.Text.AsString().XSplit("[^0-9]+", System.Text.RegularExpressions.RegexOptions.Multiline);
                int i;
                foreach (string s in str)
                {
                    i = s.AsInt(-1);
                    if (i < 1 || i > 49)
                    {
                        this.ShowDxErrorDialog("Błędne wybrane liczby!");
                        return;
                    }
                    WybraneLiczby.AddIfNotExist(i);
                }
                WybraneLiczby.Sort();
                if (WybraneLiczby.Count < 6)
                {
                    this.ShowDxErrorDialog("Za mało wybranych liczb!");
                    return;
                }
                max = (int)LottoLosowaniaTools.Kombinacja(WybraneLiczby.Count, 6);
            }
            
            PrzedzialyLiczb.Clear();
            foreach (DataRow r in rows)
            {
                if (r["WRK_LWK_TYP"].AsString() == "Liczba z przedziału" &&
                    r["WRK_LWK_TYP_WYBORU"].AsString() == "W")
                {
                    if (!PrzedzialyLiczb.ContainsKey(r["WRK_LWK_X"].AsInt()))
                    {
                        PrzedzialyLiczb.Add(r["WRK_LWK_X"].AsInt(), new int[] { r["WRK_LWK_Y"].AsInt(), r["WRK_LWK_Z"].AsInt() });
                    }
                }
            }
            int ilosc = WybraneLiczby.Count;
            

            multiThreadForm = new FormBackgroundWorkMultiThread("Szacowanie ...");
            multiThreadForm.BackgroundControl.SupportCancelation = true;
            multiThreadForm.BackgroundControl.ProgressType = ProgressType.Percentage;
            multiThreadForm.BackgroundControl.MaxProgress =(max);
            Dictionary<int,int> dic = new Dictionary<int, int>();
            int imin = 1;
            int imax = 2;
            int mul =1;
            if (ilosc > 20)
            {
                imax = 3;
                mul = 2;
            }
            int ct = 0;
            while (imax < ilosc)
            {
                dic.Add(imin, imax);
                imin = imax;
                ct++;
                if (ct == 2)
                {
                    ct = 0;
                    mul++;
                }
                imax += mul;
            }
            if (imax > ilosc)
            {
                dic.Add(imin, ilosc);
            }
            foreach (KeyValuePair<int,int> kvp in dic)
            {
                multiThreadForm.AddAction(new Action<int, int>(Szacuj), new object[] { kvp.Key, kvp.Value });
            }
            if (save)
                "".WriteToFile(fileName);
            progressReporter1.Form = multiThreadForm;
            progressReporter1.Start();
            DialogResult dlg = multiThreadForm.ShowDialog();
            progressReporter1.Stop();
            switch (dlg)
            {
                case System.Windows.Forms.DialogResult.Cancel:
                    this.ShowDxInfoDialog("Przerwa na życzenie użytkownika");
                    if (save)
                    {
                        try { File.Delete(fileName); }
                        catch { }
                    }
                    break;
                case System.Windows.Forms.DialogResult.Abort:
                    
                    this.ShowDxErrorDialog("Błąd wyliczania.");
                    if (save)
                    {
                        try { File.Delete(fileName); }
                        catch { }
                    }
                    break;
                case System.Windows.Forms.DialogResult.OK:
                    teIloscKombinacji.EditValue = wynik;
                    break;
            }
        }
        private void Szacuj(int minNum, int maxNum)
        {
            List<int> kombinacja = new List<int>();
            List<int> kombinacja2 = new List<int>();
            ActionLottoBase action;
            Dictionary<DataRow, int[]> dic = new Dictionary<DataRow, int[]>();
            Dictionary<DataRow, bool> typyWyborow = new Dictionary<DataRow, bool>();
            bool add = true;
            bool liczbySpelniajaWarkunki = true;

            foreach (DataRow r in rows)
            {
                dic.Add(r, new int[]{r["WRK_LWK_X"].AsInt(-1), 
                    r["WRK_LWK_Y"].AsInt(-1), 
                    r["WRK_LWK_Z"].AsInt(-1)});
                typyWyborow.Add(r, r["WRK_LWK_TYP_WYBORU"].AsString() == "W");
            }
            int liczba1,liczba2,liczba3,liczba4,liczba5,liczba6;
            int MaxLiczby = WybraneLiczby.Count;

            for (int l1=minNum; l1 < maxNum; l1++)
            {
                liczba1 = WybraneLiczby[l1];
                for (int l2 = l1 + 1; l2 < MaxLiczby-4; l2++)
                {
                    liczba2 = WybraneLiczby[l2];
                    for (int l3 = l2 + 1; l3 < MaxLiczby-3; l3++)
                    {
                        liczba3 = WybraneLiczby[l3];
                        for (int l4 = l3 + 1; l4 < MaxLiczby-2; l4++)
                        {
                            liczba4 = WybraneLiczby[l4];
                            for (int l5 = l4 + 1; l5 < MaxLiczby-1; l5++)
                            {
                                liczba5 = WybraneLiczby[l5];
                                for (int l6 = l5 + 1; l6 < MaxLiczby; l6++)
                                {
                                    liczba6 = WybraneLiczby[l6];
                                    if (multiThreadForm.BackgroundControl.IsCanceling)
                                        return;
                                    progressReporter1.Progress++;
                                    add = true;
                                    kombinacja.Clear();
                                    kombinacja2.Clear();
                                    kombinacja.AddRange(new int[] { liczba1, liczba2, liczba3, liczba4, liczba5, liczba6 });
                                    kombinacja2.AddRange(new int[] { liczba1, liczba2, liczba3, liczba4, liczba5, liczba6, LottoLosowaniaTools.IloscLosowan });
                                    foreach (KeyValuePair<DataRow, int[]> kvp in dic)
                                    {
                                        action = ActionLottoBase.GetActionForWyborKombinacji(kvp.Key["WRK_LWK_TYP"].ToString());
                                        if (action != null)
                                        {
                                            if (action.IsActionForLosowanie)
                                                liczbySpelniajaWarkunki = action.LiczbySpelniajaWarunki(kombinacja2, kvp.Value[0], kvp.Value[1], kvp.Value[2]);
                                            else
                                                liczbySpelniajaWarkunki = action.LiczbySpelniajaWarunki(kombinacja, kvp.Value[0], kvp.Value[1], kvp.Value[2]);
                                            if (typyWyborow[kvp.Key] != liczbySpelniajaWarkunki)
                                            {
                                                add = false;
                                                break;
                                            }
                                        }
                                    }
                                    if (add)
                                    {
                                        if (SaveToFile)
                                        {
                                            lock (lockGlobalFile)
                                            {
                                                kombinacja.AsString().AppendToFile(fileName);
                                            }
                                        }
                                        lock (lockWynik)
                                        {
                                            wynik++;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        protected override void OnActivated(EventArgs e)
        {
            base.OnActivated(e);
            if (!this.IsDesignMode())
            {
                if (teObecnaLiczbaLosowan.EditValue.AsInt() != LottoLosowaniaTools.IloscLosowan)
                    teObecnaLiczbaLosowan.EditValue = LottoLosowaniaTools.IloscLosowan;
            }
        }

        private void positionControl1_OrderChanged(object sender, EventArgs e)
        {
            //changeDetectorProvider1.RefreshObject(gvMain);
        }

        private void modeProvider1_CustomGetModes(object sender, ProgNetComponentsDx.Mode.CustomModeSettingsEventArgs e)
        {
            if (sender == colWRK_LWK_X ||
                   sender == colWRK_LWK_Y ||
                   sender == colWRK_LWK_Z)
            {
                if (modeProvider1.CurrentMode == ProgNetComponentsDx.Enums.FormMode.Edit ||
                    modeProvider1.CurrentMode == ProgNetComponentsDx.Enums.FormMode.New)
                {
                    if (!e.Row.CanRead())
                    {
                        e.IsReadOnly = true;
                        return;
                    }

                    ActionLottoBase action = ActionLottoBase.GetActionForWyborKombinacji(e.Row["WRK_LWK_TYP"].AsString());
                    if (action == null)
                    {
                        e.IsReadOnly = true;
                    }
                    else
                    {
                        if (sender == colWRK_LWK_X)
                            e.IsReadOnly = action.IsColReadOnly("X");
                        else if (sender == colWRK_LWK_Y)
                            e.IsReadOnly = action.IsColReadOnly("Y");
                        else if (sender == colWRK_LWK_Z)
                            e.IsReadOnly = action.IsColReadOnly("Z");
                    }
                }
                else
                {
                    e.IsReadOnly = true;
                }
            }
        }

        private void lueTyp_EditValueChanged(object sender, EventArgs e)
        {
            string typ = lueTyp.EditValue.AsString();
            ActionLottoBase action = ActionLottoBase.GetActionForWyborKombinacji(typ);
            if (action != null)
            {
                meTyp.Text = action.Opis.ReplaceSingleEOL();
            }
            else
            {
                meTyp.Text = "";
            }
        }

        private void gvMain_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            if (e.Column == colWRK_LWK_TYP)
            {
                gvMain.SetRowCellValue(e.RowHandle, colWRK_LWK_X, DBNull.Value);
                gvMain.SetRowCellValue(e.RowHandle, colWRK_LWK_Y, DBNull.Value);
                gvMain.SetRowCellValue(e.RowHandle, colWRK_LWK_Z, DBNull.Value);
            }
        }

        private void gvMain_FocusedRowChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs e)
        {
            DataRow row = gvMain.GetDataRow(e.FocusedRowHandle);
            if (row.CanRead())
            {
                lueTyp.EditValue = row["WRK_LWK_TYP"].AsString();
            }
        }

        private void bbiKopiuj_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (Save())
            {
                lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0].WRK_LWKG_ID = -1;
                lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0].WRK_LWKG_NAZWA = "";

                lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0].AcceptChanges();
                lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY[0].SetAdded();
                teGrupa.EditValue = "";
                int i = -1;
                foreach (DataRow r in lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI.Rows)
                {
                    r["WRK_LWK_ID"] = i--;
                    r.AcceptChanges();
                    r.SetAdded();
                }
                Tools.Globals.MdiHelper.RemoveChild(this);
                isNew = true;
                changeDetectorProvider1.ResetAll();
                modeProvider1.CurrentMode = ProgNetComponentsDx.Enums.FormMode.New;

            }
        }

        private void btnWybierzKombinacje_Click(object sender, EventArgs e)
        {
            EnsureFile();
            Select(true);
        }

        private void bbiUsun_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (this.ShowDxYNQuestionDialog("Czy napewno chcesz usunąć ten rekord?") == System.Windows.Forms.DialogResult.Yes)
            {
                this.lottoWyborKombinacjiDataSet.AcceptChanges();
                this.lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI_GRUPY.Rows[0].Delete();
                if (base.Save())
                {
                    ObjectDialogResult dlg = browser.ShowNewDialog();
                    if (dlg.DialogResult == System.Windows.Forms.DialogResult.OK)
                    {
                        this.selectDataProvider1.GetSettings(this).Parameters["GRUPA"].Value = dlg.Value.AsInt(-1);
                        GetRecords();
                    }
                    else
                    {
                        Close();
                    }
                }
                else
                {
                    this.ShowDxErrorDialog("Błąd kasowania rekordu");
                    GetRecords();
                }
            }
        }

        private void bbiNowaGrupa_ItemClick(object sender, ItemClickEventArgs e)
        {
            bool res = true;
            if (changeDetectorProvider1.HasChanges)
            {
                DialogResult dlg = this.ShowDxYNCQuestionDialog("Chcesz zapisać zmiany?");
                switch (dlg)
                {
                    case System.Windows.Forms.DialogResult.Yes:
                        res = Save();
                        break;
                    case System.Windows.Forms.DialogResult.No:
                        res = true;
                        break;
                    case System.Windows.Forms.DialogResult.Cancel:
                        return;
                }
            }
            if (res)
            {
                this.selectDataProvider1.GetSettings(this).Parameters["GRUPA"].Value = -1;
                GetRecords();
            }
        }

        private void bbiWczytaj_ItemClick(object sender, ItemClickEventArgs e)
        {
            bool res = true;
            if (changeDetectorProvider1.HasChanges)
            {
                DialogResult dlg = this.ShowDxYNCQuestionDialog("Chcesz zapisać zmiany?");
                switch (dlg)
                {
                    case System.Windows.Forms.DialogResult.Yes:
                        res = Save();
                        break;
                    case System.Windows.Forms.DialogResult.No:
                        res = true;
                        break;
                    case System.Windows.Forms.DialogResult.Cancel:
                        return;
                }
            }
            if (res)
            {
                ObjectDialogResult dlg = browser.ShowNewDialog();
                if (dlg.DialogResult == System.Windows.Forms.DialogResult.OK)
                {
                    this.selectDataProvider1.GetSettings(this).Parameters["GRUPA"].Value = dlg.Value.AsInt(-1);
                    GetRecords();
                }
            }
        }

        private void bbiSprawdzLosowanie_ItemClick(object sender, ItemClickEventArgs e)
        {
            FormSprawdzLosowanie f = new FormSprawdzLosowanie(lottoWyborKombinacjiDataSet.WRK_LOTTO_WYBOR_KOMBINACJI);
            f.ShowDialog();
        }

        private void progressReporter1_GetLabel1Text(object sender, ProgNetComponentsDx.Controls.StringEventArgs e)
        {
            lock (lockWynik)
            {
                e.Value += "\nWynik: " + wynik;
            }
        }

    }
}
